﻿using System;
using System.Collections.Generic;
using System.Linq;
using Czx.Common;
using Czx.Common.AttributesHelper;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.MappedStatements;
using IBatisNet.DataMapper.Scope;

namespace Hr.Business
{
    public class ManagerBase<T> where T : class
    {
        #region constructor

        protected static ISqlMapper Mapper { get; set; }
        protected Logger MyLogger { get; set; }

        protected ManagerBase()
        {
            Mapper = MapperFactory.Instance();
            MyLogger = Logger.GetLogger(GetType());
        }

        #endregion constructor

        private string Name
        {
            get { return typeof(T).Name; }
        }

        public virtual T Get(object id)
        {
            string statementName = string.Format("Get{0}", Name);
            LogRuntimeSql(statementName, id);
            var entity = Mapper.QueryForObject(statementName, id) as T;
            return entity;
        }

        public int GetCount()
        {
            string statementName = string.Format("{0}Count", Name);
            LogRuntimeSql(statementName, null);
            return (int)Mapper.QueryForObject(statementName, null);
        }

        public virtual object Add(T entity)
        {
            Validate(entity);
            string statementName = string.Format("Insert{0}", Name);
            LogRuntimeSql(statementName, entity);
            return Mapper.Insert(statementName, entity);
        }

        public virtual void Update(T entity)
        {
            Validate(entity);
            string statementName = string.Format("Update{0}", Name);
            LogRuntimeSql(statementName, entity);
            Mapper.Update(statementName, entity);
        }

        private void Validate(T entity)
        {
            var lst = entity.IsValid().ToList();
            if (lst.Count == 0) return;

            var r = string.Join("\r\n",
                lst.Select(t => string.Format("Error Message:{0}.{1}", typeof (T).Name, t.Message)));
            throw new Exception(r);
        }

        public virtual void Delete(object id)
        {
            string statementName = string.Format("Delete{0}", Name);
            LogRuntimeSql(statementName, id);
            Mapper.Delete(statementName, id);
        }

        public virtual IList<T> GetAll()
        {
            string statementName = string.Format("GetAll{0}", Name);
            LogRuntimeSql(statementName, null);
            return Mapper.QueryForList<T>(statementName, null);
        }

        protected virtual void LogRuntimeSql(string statementName, object paramObject)
        {
            IMappedStatement statement = Mapper.GetMappedStatement(statementName);
            if (!Mapper.IsSessionStarted)
            {
                Mapper.OpenConnection();
            }
            RequestScope scope = statement.Statement.Sql.GetRequestScope(statement, paramObject, Mapper.LocalSession);
            MyLogger.Info(scope.PreparedStatement.PreparedSql);
        }
    }
}
